package com.xcw.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 金额转换类
 * 
 * @author admin
 * 
 */
public class MoneyUtils {

	private static final Logger logger = LoggerFactory.getLogger(MoneyUtils.class);

	/**
	 * 金额 元 格式转换对象
	 */
	public static DecimalFormat FORMAT_YUAN = new DecimalFormat("0.00");

	/**
	 * 金额 分 格式转换对象
	 */
	public static DecimalFormat FORMAT_FEN = new DecimalFormat("0");

	public static void main(String[] args) {
		//Map<String,Object> map = new HashMap<String,Object>();
		//map.put("a", null);
		//System.out.println(MoneyUtils.toDoubleCent(map.get("a")));
		//calFee("10001.00","0.0059","1.00");
		//System.out.println(new BigDecimal("0.51").multiply(new BigDecimal(100)).longValue());
		//System.out.println(toDoubleYuan("1"));
	}

	/**
	 * 判断小数点后2位的数字的正则表达式
	 * @param str
	 * @return
	 */
	public static boolean isNumber(String str){
		Pattern pattern=Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$");
		Matcher match=pattern.matcher(str);
		if(match.matches()==false){
			return false;
		}else{
			return true;
		}
	}

	/**
	 * 转成 分
	 *
	 * @param obj
	 * @return
	 */
	public static Long toLongCent(Object obj) {
		if(obj == null){
			obj = 0;
		}
		return new BigDecimal(obj.toString()).multiply(new BigDecimal(100)).longValue();
	}

	/**
	 * 转成 分
	 * 
	 * @param obj
	 * @return
	 */
	public static Double toDoubleCent(Object obj) {
		if(obj == null){
			obj = 0;
		}
		return new BigDecimal(obj.toString()).multiply(new BigDecimal(100)).doubleValue();
	}

	/**
	 * 转成 分
	 * 
	 * @param obj
	 * @return
	 */
	public static String toStrCent(Object obj) {
		String cent = formatCent(toDoubleCent(obj));
		return cent == null || "0".equals(cent) ? "0" : cent;
	}

	/**
	 * 转成 元
	 * 
	 * @param obj
	 * @return
	 */
	public static Double toDoubleYuan(Object obj) {
		if(obj == null){
			obj = 0;
		}
		return new BigDecimal(obj.toString()).divide(new BigDecimal(100),2, BigDecimal.ROUND_UP).doubleValue();
	}

	/**
	 * 转成 元
	 * 
	 * @param obj
	 * @return
	 */
	public static String toStrYuan(Object obj) {
		String yuan = formatYuan(toDoubleYuan(obj));
		return yuan == null || "0.00".equals(yuan) ? "" : yuan;
	}

	/**
	 * 格式化分 ，变成没有小数点的数字字符串
	 * 
	 * @param obj
	 * @return
	 */
	private static String formatCent(Object obj) {
		return FORMAT_FEN.format(obj);
	}

	/**
	 * 格式化元 ，变成两位小数点的数字字符串
	 * 
	 * @param obj
	 * @return
	 */
	private static String formatYuan(Object obj) {
		return FORMAT_YUAN.format(obj);
	}

	/**
	 * 百分比转化成小数
	 *
	 * @param obj
	 * @return
	 */
	public static String formatPercent(Object obj) {
		if(obj == null){
			return null;
		}
		return new BigDecimal(obj.toString()).divide(new BigDecimal(100)).toString();
	}
	 
		/**
		 * 计算费用，最低收取 1分 [提供精确的小数位四舍五入处理,保留2位小数。 ]
		 * @param rate  点数
		 * @param txamt 分
		 * @param low   分
		 * @return 分
		 */
		public static int calculate(String rate,String txamt,double low) {
			double rate_ = toDoubleYuan(rate);
			double txamt_= toDoubleYuan(txamt);
		
			Double tmpTxAmt  = mul(rate_ , txamt_) ;
			Double tmpTxAmt_ = mul(round(tmpTxAmt.doubleValue(),2),100.00);
			
			if(tmpTxAmt_.intValue() <=0 ){
				tmpTxAmt_ = low ;
			}
			
			return tmpTxAmt_.intValue();
		}
		
		/**
		 * Double相乘
		 * @param v1
		 * @param v2
		 * @return
		 */
		public static Double mul(Double v1, Double v2) {  
			   BigDecimal b1 = new BigDecimal(v1.toString());  
			   BigDecimal b2 = new BigDecimal(v2.toString());  
			   return new Double(b1.multiply(b2).doubleValue());  
		}
		
		/**
		 * Double相除
		 * @param v1
		 * @param v2
		 * @param scale 小数点后保留几位
		 * @return
		 */
		public static Double div(Double v1, Double v2, int scale) {
			   BigDecimal b1 = new BigDecimal(v1.toString());
			   BigDecimal b2 = new BigDecimal(v2.toString());
			   return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
		}
		
		/** 
		* 提供精确的小数位四舍五入处理。 
		* @param v 需要四舍五入的数字 
		* @param scale 小数点后保留几位 
		* @return 四舍五入后的结果 
		*/  
		public static double round(double v, int scale) {  
		   BigDecimal b = new BigDecimal(Double.toString(v));  
		   return b.divide(new BigDecimal("1"), scale, BigDecimal.ROUND_HALF_UP).doubleValue();  
		}
		
		/**
		 * 费用相加
		 * @param fee
		 * @param serverFee
		 * @return
		 */
		public static int add(Integer fee,String serverFee) {
			return fee.intValue() + Integer.valueOf(serverFee).intValue();
		}
		
		// 判断一个字符串是否都为数字
		public static boolean isDigit(String strNum) {
			Pattern pattern = Pattern.compile("^[0-9]+(.[0-9]+)?$");
			Matcher matcher = pattern.matcher((CharSequence) strNum);
			return matcher.matches();
		}

		/**
		 * 计算手续费
		 * @param payAmount 单位元，精确到分 0.00
		 * @param rate	精确到小数点后4位 0.0000
		 * @param drawFee 单位元，精确到分 0.00
		 * @return
		 */
		public static Map<String,Object> calFee(String payAmount,String rate,String drawFee){
			logger.debug("payAmount={},rate={},drawFee={}", payAmount,rate,drawFee);
			Double payAmount_cent_double = (new BigDecimal(payAmount).multiply(new BigDecimal(100))).doubleValue();
			String payAmount_cent_int = String.valueOf(payAmount_cent_double.intValue());
			String rate_percent = (new BigDecimal(rate).multiply(new BigDecimal(100))).toString();
			Integer hand_fee_cent_int = MoneyUtils.calculate(rate_percent, payAmount_cent_int, 2);
			logger.debug("手续费{}分=交易金额{}分*费率{}%", hand_fee_cent_int,payAmount_cent_int,rate_percent);
			Double drawFee_cent_double = (new BigDecimal(drawFee).multiply(new BigDecimal(100))).doubleValue();
			String drawFee_cent_int = String.valueOf(drawFee_cent_double.intValue());
			logger.debug("手续费{}分，服务费{}分", hand_fee_cent_int,drawFee_cent_int);
			Integer total_fee_cent_int = MoneyUtils.add(hand_fee_cent_int, drawFee_cent_int);//手续费+服务费=交易总手续费
			logger.debug("交易总费用{}分", total_fee_cent_int);
			Integer reality_account_amt_cent_int = payAmount_cent_double.intValue() - total_fee_cent_int.intValue();
			logger.debug("实际到账金额{}分=交易金额{}分-交易总费用{}分",
					reality_account_amt_cent_int,payAmount_cent_double.intValue(),total_fee_cent_int.intValue());

			Map<String,Object> calFeeRetMap = new HashMap<String,Object>();
			calFeeRetMap.put("hand_fee_yuan",(new BigDecimal(hand_fee_cent_int.toString()).divide(new BigDecimal("100"),2,BigDecimal.ROUND_HALF_UP)).toString());
			calFeeRetMap.put("total_fee_yuan",(new BigDecimal(total_fee_cent_int.toString()).divide(new BigDecimal("100"),2,BigDecimal.ROUND_HALF_UP)).toString());
			calFeeRetMap.put("reality_account_amt_yuan",(new BigDecimal(reality_account_amt_cent_int.toString()).divide(new BigDecimal("100"),2,BigDecimal.ROUND_HALF_UP)).toString());
			logger.info("calFeeRetMap={}",calFeeRetMap);
			return calFeeRetMap;
		}
}
